/*
 * @Description:
 * @Version: 2.0
 * @Autor: wiz
 * @Date: 2023-06-28 08:19:44
 * @LastEditors: zss
 * @LastEditTime: 2024-10-24 13:56:52
 */
import { ifs } from '@/services';
import { N_oContextMenu, N_oSimpleToolbar } from '@/types';
import {
  Cell,
  CellView,
  Edge,
  EdgeView,
  Graph,
  Model,
  Node,
  NodeView,
  View
} from '@antv/x6';
import { Options } from '@antv/x6/lib/graph/options';
import Vue from 'vue';
import { I_cmd } from './command';

import base from './classes';

namespace N_cFlowchart {
  export type I_editorState =
    | 'none'
    | 'modify'
    | 'add'
    | 'canEdit'
    | 'noHandle';
  export type I_workMode = 'edit' | 'view';
  export class T_conf extends base.T_conf {}
  export interface I_conf extends T_conf {}
  export class T_graphOpts extends base.T_graphOpts {}
  export interface I_graphOpts extends T_graphOpts {}
  export interface I_cFlowCmd extends I_cmd {}
  export interface x6NodeMetadata extends Node.Metadata {}
  export interface x6EdgeMetadata extends Edge.Metadata {}
  export interface x6CellMetadata extends Cell.Metadata {}
  export class x6Cell extends Cell {}
  export class x6CellView extends CellView {}
  export class x6View extends View {}
  export class x6Edge extends Edge {}
  export class x6Graph extends Graph {}
  export class x6Model extends Model {}
  export class x6Node extends Node {}
  export class x6NodeView extends NodeView {}
  export class x6EdgeView extends EdgeView {}
  // eslint-disable-next-line no-shadow
  export enum EVENTS {
    // 单击
    CELL_CLICK = 'cell:click',
    NODE_CLICK = 'node:click',
    EDGE_CLICK = 'edge:click',
    BLANK_CLICK = 'blank:click',
    // 双击
    CELL_DBLCLICK = 'cell:dblclick',
    NODE_DBLCLICK = 'node:dblclick',
    EDGE_DBLCLICK = 'edge:dblclick',
    BLANK_DBLCLICK = 'blank:dblclick',
    // 右键
    CELL_CONTEXTMENU = 'cell:contextmenu',
    NODE_CONTEXTMENU = 'node:contextmenu',
    EDGE_CONTEXTMENU = 'edge:contextmenu',
    BLANK_CONTEXTMENU = 'blank:contextmenu',
    // 鼠标按下
    CELL_MOUSEDOWN = 'cell:mousedown',
    NODE_MOUSEDOWN = 'node:mousedown',
    EDGE_MOUSEDOWN = 'edge:mousedown',
    BLANK_MOUSEDOWN = 'blank:mousedown',
    // 移动鼠标
    CELL_MOUSEMOVE = 'cell:mousemove',
    NODE_MOUSEMOVE = 'node:mousemove',
    EDGE_MOUSEMOVE = 'edge:mousemove',
    BLANK_MOUSEMOVE = 'blank:mousemove',
    // 鼠标抬起
    CELL_MOUSEUP = 'cell:mouseup',
    NODE_MOUSEUP = 'node:mouseup',
    EDGE_MOUSEUP = 'edge:mouseup',
    BLANK_MOUSEUP = 'blank:mouseup',
    // 鼠标滚轮
    CELL_MOUSEWHEEL = 'cell:mousewheel',
    NOD_EMOUSEWHEEL = 'node:mousewheel',
    EDGE_MOUSEWHEEL = 'edge:mousewheel',
    BLANK_MOUSEWHEEL = 'blank:mousewheel',
    // 鼠标进入
    CELL_MOUSEENTER = 'cell:mouseenter',
    NODE_MOUSEENTER = 'node:mouseenter',
    EDGE_MOUSEENTER = 'edge:mouseenter',
    GRAPH_MOUSEENTER = 'graph:mouseenter',
    // 鼠标离开
    CELL_MOUSELEAVE = 'cell:mouseleave',
    NODE_MOUSELEAVE = 'node:mouseleave',
    EDGE_MOUSELEAVE = 'edge:mouseleave',
    GRAPH_MOUSELEAVE = 'graph:mouseleave',
    // 画布缩放，平移
    GRAPH_SCALE = 'scale', // 缩放画布时触发，sx 和 sy 是缩放比例，ox 和 oy 是缩放中心。
    GRAPH_RESIZE = 'resize', // 改变画布大小时触发，width 和 height 是画布大小。
    GRAPH_TRANSLATE = 'translate', // 平移画布时触发，tx 和 ty 分别是 X 和 Y 轴的偏移量。
    // 节点或边缩放/平移/旋转
    NODE_MOVE = 'node:move', // 开始移动节点时触发。
    NODE_MOVING = 'node:moving', // 移动节点时触发
    NODE_MOVED = 'node:moved', // 移动节点后触发
    EDGE_MOVE = 'edge:move', // 开始移动边时触发
    EDGE_MOVING = 'edge:moving', // 移动边时触发
    EDGE_MOVED = 'edge:moved', // 移动边后触发
    NODE_RISIZE = 'node:resize', // 开始调整节点大小时触发。
    NODE_RESIZING = 'node:resizing', // 调整节点大小时触发
    NODE_RESIZED = 'node:resized', // 调整节点大小后触发
    EDGE_RISIZE = 'edge:resize', // 开始旋转节点时触发
    EDGE_RESIZING = 'edge:resizing', // 旋转节点时触发
    EDGE_RESIZED = 'edge:resized', // 旋转节点后触发
    // 节点嵌入
    NODE_EMBED = 'node:embed', // 开启嵌入，在开始拖动节点时触发。
    NODE_EMBEDDING = 'node:embedding', // 寻找目标节点过程中触发。
    NODE_EMBEDDED = 'node:embedded', // 完成节点嵌入后触发
    // 画布渲染完成
    RENDER_DONE = 'render:done', // 在调用 fromJSON 或者 resetCells 后监听画布完成渲染事件，这时候可以使用 render:done 事件来监听 (2.15.1 版本新增)
    // 添加/删除/修改
    // 参考:https://x6.antv.vision/zh/docs/tutorial/intermediate/events/#gatsby-focus-wrapper
    //
    // cell:change:*
    // node:change:*（仅当 cell 是节点时才触发） node:change:att
    // edge:change:*（仅当 cell 是边时才触发）
    // cell:change:zIndex
    // node:change:zIndex（仅当 cell 是节点时才触发）
    // edge:change:zIndex（仅当 cell 是边时才触发）
    //     其他 change 事件如下列表，回调函数的参数与上面提到的 change:zIndex 的参数结构一致。

    // Cell

    // change:*
    // change:attrs
    // change:zIndex
    // change:markup
    // change:visible
    // change:parent
    // change:children
    // change:view
    // change:data
    // Node

    // change:size
    // change:angle
    // change:position
    // change:ports
    // change:portMarkup
    // change:portLabelMarkup
    // change:portContainerMarkup
    // ports:added
    // ports:removed
    // Edge

    // change:source
    // change:target
    // change:terminal
    // change:router
    // change:connector
    // change:vertices
    // change:labels
    // change:defaultLabel
    // change:toolMarkup
    // change:doubleToolMarkup
    // change:vertexMarkup
    // change:arrowheadMarkup
    // vertexs:added
    // vertexs:removed
    // labels:added
    // labels:removed
    //     除了上述这些内置的 Key，我们也支持监听自定义的 Key，例如
    // cell.on('change:custom', ({ cell, current, previous, options}) => {
    // })
    // 当通过 cell.prop('custom', 'any data') 方法修改 custom 属性的值时将触发 change:custom 事件。

    EDGE_CONNECTED = 'edge:connected', // 连接、取消边edge时触发
    EDGE_REMOVED = 'edge:removed', // 删除边edge时触发
    NODE_REMOVED = 'node:removed', // 删除边edge时触发

    // 检查以下事件名字是否有误（:remove等）
    ADDED = 'added',
    CELL_ADDED = 'cell:added',
    NODE_ADDED = 'node:added',
    EDGE_ADDED = 'edge:added',
    REMOVE = 'remove',
    CELL_REMOVE = 'cell:remove',
    NODE_REMOVE = 'node:remove',
    EDGE_REMOVE = 'edge:remove',
    CHANGED = 'changed',
    CELL_CHANGED = 'cell:changed',
    NODE_CHANGED = 'node:changed',
    EDGE_CHANGED = 'edge:changed',
    // 动画
    TRANSITION_START = 'transition:start', // 动画开始时触发。
    TRANSITION_PROGRESS = 'transition:progress', // 动画进行中触发。
    TRANSITION_COMLETE = 'transition:complete', // 动画完成时触发
    TRANSITION_STOP = 'transition:stop', // 动画被停止时触发
    TRANSITION_FINISH = 'transition:finish' // 动画完成或被停止时触发
  }
  export interface I_eventParams {
    node?: x6Node;
    edge?: x6Edge;
    cell?: x6Cell;
    view?: x6NodeView | x6EdgeView;
    x: number;
    y: number;
    e: any;
  }
  export interface I_edgeConnectParams {
    e: any; // 鼠标事件对象
    edge: x6Edge; // 边
    view: EdgeView; // 边的视图
    isNew: boolean; // 是否是新创建的边
    type: Edge.TerminalType; // 操作的是起始箭头还是终止箭头（'source' | 'target'）

    previousCell?: Cell | null; // 交互前连接到的节点/边
    previousView?: CellView | null; // 交互前连接到的节点/边的视图
    previousPort?: string | null; // 交互前连接到的链接桩 ID
    // previousPoint?: Point.PointLike | null; // 交互前连接到的点（将边的终端从空白处拖动到节点/边上时记录起始终端的位置）
    previousPoint?: any | null;
    previousMagnet?: Element | null; // 交互前连接到的元素

    currentCell?: Cell | null; // 交互后连接到的节点/边
    currentView?: CellView | null; // 交互后连接到的节点/边的视图
    currentPort?: string | null; // 交互后连接到的链接桩 ID
    // currentPoint?: Point.PointLike | null; // 交互后连接到的点（将边的终端从节点/边上拖动到空白处时记录拖动后终端的位置）
    currentPoint?: any | null; // 交互后连接到的点（将边的终端从节点/边上拖动到空白处时记录拖动后终端的位置）
    currentMagnet?: Element | null; // 交互后连接到的元素
  }

  export interface I_edgeEventParams {
    edge: x6Edge;
    index: Number;
    options?: any;
  }
  export interface I_nodeEventParams {
    node: x6Node;
    index: Number;
    options?: any;
  }

  export interface I_graphOpt extends Options.Manual {}

  export interface I_node {
    // 注册的节点名
    name: string;
    // 节点类，直接或间接继承 Node 的类。
    cls:
      | Node.Definition
      | (Node.Config & {
          inherit?: string | Node.Definition;
        });
    // 重名时是否覆盖，默认为 false 不覆盖（重名时报错）。
    overwrite?: boolean;
  }
  export interface I_vueNode {
    shape: string;
    width: number;
    height: number;
    component: typeof Vue;
  }
  export interface I_edge {
    // 注册的边名
    name: string;
    // 节点类，直接或间接继承 Node 的类。
    options:
      | Edge.Definition
      | (Edge.Config & {
          inherit?: string | Edge.Definition;
        });
    // 重名时是否覆盖，默认为 false 不覆盖（重名时报错）。
    overwrite?: boolean;
  }
  export type I_item = Edge.Metadata | Node.Metadata;
  export interface cFlowchart extends Vue {
    /* 组件名 */
    name: string;

    G_compName: string;

    /* 组件箱信息对象 */
    GT_compBoxInfo: ifs.I_compBoxInfo;

    /* 组件箱对象 */
    GT_compBox: ifs.I_compBox;

    /* 组件箱识别ID */
    G_compID: string;

    GT_cmd: I_cmd;

    graphContainer: string;

    isMask: boolean;

    showMinimap: boolean;
    isFullScreen: boolean;
    showContextMenu: boolean;
    showStencil: boolean;
    toolbarList: Array<N_oSimpleToolbar.I_Conf>;

    graph: x6Graph;
    zoomToFit(opt: { padding: number; preserveAspectRatio: boolean });
    createEdge(item: N_cFlowchart.I_item): x6Edge;
    createNode(item: N_cFlowchart.I_item): x6Node;
    getCells(): N_cFlowchart.x6Cell[];
    getNodes(): N_cFlowchart.x6Node[];
    getEdges(): N_cFlowchart.x6Edge[];
    // 更新注册从配置文件 注册节点和边不更新
    updRegister(): void;
    hideContextMenu(): void;
    displayContextMenu(
      pos: N_oContextMenu.I_showPosition,
      contextMenuItems: N_oContextMenu.I_menuItem[],
      e: N_cFlowchart.I_eventParams
    ): void;
    addNode(p: N_cFlowchart.x6NodeMetadata): void;

    addEdge(p: N_cFlowchart.x6EdgeMetadata): void;

    removeNode(id: string): void;

    removeEdge(id: string): void;
    layout(): void;
    setShowStencli(p: boolean): void;

    setShowToolbar(p: boolean): void;

    setShowMinimap(p: boolean): void;
    reLoadDataFromJson(json: string): void;
    isDenyEdit(): boolean;

    getLayoutObj(): any;
  }

  export type I_toolbarEventFun = (p: cFlowchart) => Promise<boolean>;

  export type I_shortcutsFun = Function;
}
export { N_cFlowchart };
